package org.jin.jinaicode.service.impl;

import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.jin.jinaicode.common.BaseResponse;
import org.jin.jinaicode.common.ResultUtils;
import org.jin.jinaicode.exception.BusinessException;
import org.jin.jinaicode.exception.ErrorCode;
import org.jin.jinaicode.exception.ThrowUtils;
import org.jin.jinaicode.model.dto.user.UserUpdateDTO;
import org.jin.jinaicode.model.entity.User;
import org.jin.jinaicode.mapper.UserMapper;
import org.jin.jinaicode.model.vo.UserLoginVO;
import org.jin.jinaicode.model.vo.UserRegisterVO;
import org.jin.jinaicode.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.jin.jinaicode.constant.UserConstant.USER_LOGIN_STATE;

/**
 * 用户 服务层实现。
 *
 * @author 小堇
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;

    // 盐值
    private static final String SALT = "jinai";

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // 检查邮箱格式是否正确
    private static final String EMAIL_REGEX = "^[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+(\\.[a-zA-Z0-9_!#$%&'*+/=?`{|}~^-]+)*@" +
            "([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}$";
    private static final Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEX);

    @Override
    public boolean isValidEmail(String email) {
        if (email == null)
            return false;
        Matcher matcher = EMAIL_PATTERN.matcher(email);
        return matcher.matches();
    }

    /**
     * 生成10位随机数字分享码
     */
    private String generateShareCode() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }

    /**
     * 验证分享码是否有效，并返回邀请人用户
     */
    private User validateInviteCode(String inviteUtm) {
        if (StringUtils.isBlank(inviteUtm)) {
            return null;
        }

        // 查询邀请码对应的用户
        QueryWrapper queryWrapper = QueryWrapper.create();
        queryWrapper.eq("shareCode", inviteUtm);
        queryWrapper.eq("isDelete", 0); // 确保用户未被删除
        return userMapper.selectOneByQuery(queryWrapper);
    }

    /**
     * 更新邀请人的邀请列表
     */
    private void updateInviterList(User inviter, Long newUserId) {
        if (inviter == null || newUserId == null) {
            return;
        }

        String currentInviteList = inviter.getHavaInviteUser();
        if (StringUtils.isBlank(currentInviteList)) {
            inviter.setHavaInviteUser(String.valueOf(newUserId));
        } else {
            inviter.setHavaInviteUser(currentInviteList + "," + newUserId);
        }

        // 更新邀请人信息
        userMapper.update(inviter);
    }

    @Override
    public BaseResponse<UserRegisterVO> userRegister(String userAccount, String email, String captcha,
            String userPassword, String checkPassword, String inviteUtm) {
        // 1. 校验所有字段是否为空
        if (StringUtils.isAllBlank(userAccount, userPassword, checkPassword, email, captcha)) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(400, "请输入完整信息");
        }

        // 2. 校验账户长度
        if (userAccount.length() < 4) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(400, "账号长度过短");
        }

        // 3.检查邮箱格式是否正确
        if (!isValidEmail(email)) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(400, "邮箱格式不正确");
        }

        // 检验验证码和Redis中储存的是否一致
        // 构造Redis键并获取存储的验证码
        String redisKey = "email:code:" + email.toLowerCase();
        String storedCode = (String) redisTemplate.opsForValue().get(redisKey);

        // 验证码检查
        if (storedCode == null) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(50001, "验证码已过期");
        }
        if (!storedCode.equals(captcha)) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(50001, "验证码错误");
        }

        // 4. 校验密码长度
        if (userPassword.length() < 8 || checkPassword.length() < 8) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(400, "密码长度不得小于8位");
        }

        // 5. 账户不能重复
        QueryWrapper queryWrapper = QueryWrapper.create();
        queryWrapper.eq("userAccount", userAccount);
        long count = userMapper.selectCountByQuery(queryWrapper);
        if (count > 0) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(400, "当前账户已存在");
        }

        // 6. 账户不包含特殊字符
        String validPattern = "^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$";
        Pattern pattern = Pattern.compile(validPattern);
        Matcher matcher = pattern.matcher(userAccount);
        boolean matches = matcher.matches();
        if (!matches) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(400, "账户不得包含特殊字符");
        }

        // 7. 密码和校验密码是否相同
        if (!userPassword.equals(checkPassword)) {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(400, "两次输入的密码不同，请检查");
        }

        // 8. 密码加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        // 9. 生成分享码
        String shareCode = generateShareCode();

        // 10. 验证邀请码并获取邀请人信息
        User inviter = validateInviteCode(inviteUtm);

        // 11. 向用户数据库插入数据
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        user.setEmail(email);
        user.setShareCode(shareCode);

        // 如果邀请码有效，设置邀请关系
        if (inviter != null) {
            user.setInviteUser(inviter.getId());
        }

        boolean save = this.save(user);
        if (save) {
            // 如果邀请码有效，更新邀请人的邀请列表
            if (inviter != null) {
                updateInviterList(inviter, user.getId());
            }

            UserRegisterVO userRegisterVO = UserRegisterVO.builder()
                    .id(user.getId().intValue()) // 转换Long到Integer
                    .userAccount(user.getUserAccount())
                    .email(user.getEmail()) // 改用email字段而不是phone
                    .shareCode(user.getShareCode()) // 添加分享码到返回结果
                    .build();
            return ResultUtils.success(userRegisterVO);
        } else {
            return (BaseResponse<UserRegisterVO>) ResultUtils.error(500, "用户注册失败");
        }
    }

    @Override
    public BaseResponse<UserLoginVO> userLogin(String userAccount, String email, String userPassword,
            HttpServletRequest request) {
        // 校验参数
        if (StringUtils.isAllBlank(userAccount, email)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请输入完整信息");
        }

        // 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        // 查询
        QueryWrapper queryWrapperFirst = new QueryWrapper();
        queryWrapperFirst.eq("userAccount", userAccount);
        queryWrapperFirst.eq("userPassword", encryptPassword);
        QueryWrapper queryWrapperSecond = new QueryWrapper();
        queryWrapperSecond.eq("email", email);
        queryWrapperSecond.eq("userPassword", encryptPassword);
        User user = userMapper.selectOneByQuery(queryWrapperFirst);
        if (user == null) {
            user = userMapper.selectOneByQuery(queryWrapperSecond);
        }
        if (user == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号或密码错误");
        }
        // 记录用户登录状态
        request.getSession().setAttribute(USER_LOGIN_STATE, user);
        return ResultUtils.success(getLoginUserVO(user));
    }

    @Override
    public UserLoginVO getLoginUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserLoginVO userLoginVO = new UserLoginVO();
        BeanUtils.copyProperties(user, userLoginVO);
        return userLoginVO;
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        Object attribute = request.getSession().getAttribute(USER_LOGIN_STATE);
        User currentUser = (User) attribute;
        if (currentUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }
        // 从数据查询当前用户信息
        User user = this.getById(currentUser.getId());
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "用户不存在");
        }
        return user;

    }

    @Override
    public BaseResponse<UserLoginVO> updateUserInfo(UserUpdateDTO userUpdateDTO, HttpServletRequest request) {
        if (userUpdateDTO == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }

        // 获取当前登录用户
        User loginUser = getLoginUser(request);

        // 如果传入了ID，需要验证是否为当前登录用户
        if (userUpdateDTO.getId() != null && !loginUser.getId().equals(userUpdateDTO.getId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限");
        }

        // 创建更新对象
        User user = new User();
        user.setId(loginUser.getId());

        // 设置需要更新的字段
        if (StringUtils.isNotBlank(userUpdateDTO.getUserName())) {
            user.setUserName(userUpdateDTO.getUserName());
        }
        if (StringUtils.isNotBlank(userUpdateDTO.getUserAvatar())) {
            user.setUserAvatar(userUpdateDTO.getUserAvatar());
        }
        if (StringUtils.isNotBlank(userUpdateDTO.getUserProfile())) {
            user.setUserProfile(userUpdateDTO.getUserProfile());
        }
        if (StringUtils.isNotBlank(userUpdateDTO.getEmail())) {
            // 验证邮箱格式
            if (!isValidEmail(userUpdateDTO.getEmail())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱格式不正确");
            }
            // 验证邮箱是否已被其他用户使用
            QueryWrapper queryWrapper = QueryWrapper.create();
            queryWrapper.eq("email", userUpdateDTO.getEmail());
            queryWrapper.ne("id", loginUser.getId());
            long count = userMapper.selectCountByQuery(queryWrapper);
            if (count > 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "该邮箱已被使用");
            }
            user.setEmail(userUpdateDTO.getEmail());
        }

        // 更新数据库
        boolean result = this.updateById(user);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "更新失败");

        // 更新成功后，获取最新的用户信息
        User updatedUser = this.getById(loginUser.getId());

        // 更新Session中的用户信息
        request.getSession().setAttribute(USER_LOGIN_STATE, updatedUser);

        // 返回脱敏后的用户信息
        return ResultUtils.success(getLoginUserVO(updatedUser));
    }

}
